﻿/**	rebind_type.hpp
 *	----	Create Time Stamp:	--2005-09-18 01:43:12--
 *-----------------------------------------------------------------------------
 *	Mean	:类型方面的一些扩展， 通过变量来重定义类型
 *	Author	:Nick Shallery	(nicknide@gmail.com)
 *	Version	:1.0.12.13	(2008-12-21 14:48:55)
 *-----------------------------------------------------------------------------
**/	/*YOU HAVE ALL LEFT WITH THIS CODE WHILE YOU KEEP COMMENT IN EVERY COPY.*/


#if			!defined(__LOLIX__TOY__REBIND_TYPE__K_IN_G__)
#define		__LOLIX__TOY__REBIND_TYPE__K_IN_G__

#if		defined(__cplusplus)

namespace lolix{namespace toy{
namespace rebind_type
{
	template <unsigned long long type_value>
	class int2type;
	template <typename base_type>
	class type2int;
	//	把基本类型加上指针
	//template <typename base_type, unsigned long long ptr_value/*, unsigned long long const_value*/>
	//class type2truetype;

	//	把基本类型加上指针
	template <typename base_type, unsigned long long ptr_value>
	class type2truetype
	{
	public:
		typedef
			typename type2truetype
			<
			base_type*
			,ptr_value-1
			>::true_type
			true_type;
	};

	template <typename base_type>
	class type2truetype<base_type, 0/*, 0*/>
	{
	public:
		typedef base_type true_type;
	};


	//	扩展类型还原为基本类型
	//template <typename true_type>
	//class type2basetype;

	//	扩展类型还原为基本类型
	template <typename true_type>
	struct type2basetype
	{
		typedef true_type	base_type;
		enum{ ptr_value = 0	};
	};


	template <typename true_t>
	struct type2basetype<true_t*>
	{
		typedef	typename type2basetype<true_t>::base_type base_type;
		enum{ ptr_value = type2basetype<true_t>::ptr_value+1	};
	};


	template <typename true_type>
	struct type2basetype<const true_type*>
	{
		typedef	typename type2basetype<true_type>::base_type base_type;
		enum{ ptr_value = type2basetype<true_type>::ptr_value+1	};
	};

	template<unsigned long long type_size, unsigned long long ptr_size/*, unsigned long long const_size*/>
	struct TypeInfoStruct
	{
		char	type_value[type_size];
		char	ptr_value[ptr_size];
	};

	template<typename t_type>
	TypeInfoStruct
		<
		type2int<typename type2basetype<t_type>::base_type>::type_value
		,type2basetype<t_type>::ptr_value + 1
		>
	AnalysisTypeInfo(const t_type&);

	template<typename t_type>
	char (*get_value_type(const t_type&))[type2int<typename type2basetype<t_type>::base_type>::type_value];
	template<typename t_type>
	char (*get_ptr_value(const t_type&))[type2basetype<t_type>::ptr_value + 1];

}
}}


namespace lolix{namespace toy{namespace _help{
	template<typename T, int ID>
	class note_type_base
	{
	public:
		typedef T type;
		enum {id = ID};
	};

	template<int Key>
	class note_type;
}}}


#define		LOLIX_DEF__REGIST_TYPE_ENTER		LOLIX_DEF__REGIST_TYPE_TYPE
#define		LOLIX_DEF__REGIST_TYPE_TYPE			LOLIX_DEF__REGIST_TYPE_ENTER_COUNTER(__COUNTER__)
#define		LOLIX_DEF__REGIST_TYPE_ENTER_COUNTER(COUNTER)		\
	template<>\
	class lolix::toy::_help::note_type<COUNTER>\
		: public note_type_base< 
#define		LOLIX_DEF__REGIST_TYPE_ID			,
#define		LOLIX_DEF__REGIST_TYPE_LEAVE		LOLIX_DEF__REGIST_TYPE_END
#define		LOLIX_DEF__REGIST_TYPE_END			LOLIX_DEF__REGIST_TYPE_LEAVE_COUNTER(__COUNTER__-1)
#define		LOLIX_DEF__REGIST_TYPE_LEAVE_COUNTER(COUNTER)	\
									>\
	{};\
	LOLIX_DEF__REGIST_TYPE(::lolix::toy::_help::note_type<(COUNTER)>::type, ::lolix::toy::_help::note_type<(COUNTER)>::id);

#define		LOLIX_DEF__SYS_REGIST_TYPE_BEGIN	LOLIX_DEF__REGIST_TYPE_ENTER
#define		LOLIX_DEF__SYS_REGIST_TYPE_END		LOLIX_DEF__REGIST_TYPE_ID  __COUNTER__ LOLIX_DEF__REGIST_TYPE_LEAVE_COUNTER(__COUNTER__-2)

#if			!defined(_MSC_VER)
#define		LOLIX_DEF__REGIST_TYPE(t_type, t_value)	namespace lolix{namespace toy{namespace rebind_type{\
	template<> class int2type<(t_value)>{public:typedef type2basetype< t_type >::base_type base_type;};\
	template<> class type2int< type2basetype< t_type >::base_type >{public:enum{type_value = (t_value)};};}}}
#else	//	!defined(_MSC_VER)
#define		LOLIX_DEF__REGIST_TYPE(t_type, t_value)	\
	template<> class ::lolix::toy::rebind_type::int2type<(t_value)>{public:typedef type2basetype< t_type >::base_type base_type;};\
	template<> class ::lolix::toy::rebind_type::type2int< ::lolix::toy::rebind_type::type2basetype< t_type >::base_type >{public:enum{type_value = (t_value)};}
#endif	//	!defined(_MSC_VER)

#define		LOLIX_DEF__REBIND_TYPE(true_value)		\
	::lolix::toy::rebind_type::type2truetype< ::lolix::toy::rebind_type::int2type< sizeof(*::lolix::toy::rebind_type::get_value_type(true_value)) >::base_type \
	,sizeof(*::lolix::toy::rebind_type::get_ptr_value(true_value)) - 1 \
	>::true_type

#define		LOLIX_DEF__GET_ID_BY_TYPE( t_type )		(::lolix::toy::type2int<::lolix::toy::rebind_type::type2basetype< t_type >::base_type>::type_value)
#define		LOLIX_DEF__GET_TYPE_BY_ID( t_value )		::lolix::toy::rebind_type::int2type< t_value >::base_type

#if			defined(_MSC_VER)
namespace lolix{namespace toy{namespace rebind_type
{
	enum { COUNTER_BEGIN = __COUNTER__ };
}}}

#define LOLIX_DEF__SYS_REGIST_TYPE(type)	LOLIX_DEF__REGIST_TYPE(type, __COUNTER__ - ::lolix::toy::rebind_type::COUNTER_BEGIN - 1)
LOLIX_DEF__SYS_REGIST_TYPE(void);
LOLIX_DEF__SYS_REGIST_TYPE(bool);
LOLIX_DEF__SYS_REGIST_TYPE(char);
LOLIX_DEF__SYS_REGIST_TYPE(unsigned char);
LOLIX_DEF__SYS_REGIST_TYPE(short);
LOLIX_DEF__SYS_REGIST_TYPE(unsigned short);
LOLIX_DEF__SYS_REGIST_TYPE(int);
LOLIX_DEF__SYS_REGIST_TYPE(unsigned int);
LOLIX_DEF__SYS_REGIST_TYPE(long);
LOLIX_DEF__SYS_REGIST_TYPE(unsigned long);
LOLIX_DEF__SYS_REGIST_TYPE(long long);
LOLIX_DEF__SYS_REGIST_TYPE(unsigned long long);
LOLIX_DEF__SYS_REGIST_TYPE(float);
LOLIX_DEF__SYS_REGIST_TYPE(double);
LOLIX_DEF__SYS_REGIST_TYPE(long double);
#else	//	defined(_MSC_VER)
namespace lolix{namespace toy{namespace rebind_type{enum { COUNTER_BEGIN = __LINE__};}}}
#define LOLIX_DEF__SYS_REGIST_TYPE(type)	LOLIX_DEF__REGIST_TYPE(type, __LINE__ - COUNTER_BEGIN - 2)
LOLIX_DEF__SYS_REGIST_TYPE(void);
LOLIX_DEF__SYS_REGIST_TYPE(bool);
LOLIX_DEF__SYS_REGIST_TYPE(char);
LOLIX_DEF__SYS_REGIST_TYPE(unsigned char);
LOLIX_DEF__SYS_REGIST_TYPE(short);
LOLIX_DEF__SYS_REGIST_TYPE(unsigned short);
LOLIX_DEF__SYS_REGIST_TYPE(int);
LOLIX_DEF__SYS_REGIST_TYPE(unsigned int);
LOLIX_DEF__SYS_REGIST_TYPE(long);
LOLIX_DEF__SYS_REGIST_TYPE(unsigned long);
LOLIX_DEF__SYS_REGIST_TYPE(long long);
LOLIX_DEF__SYS_REGIST_TYPE(unsigned long long);
LOLIX_DEF__SYS_REGIST_TYPE(float);
LOLIX_DEF__SYS_REGIST_TYPE(double);
LOLIX_DEF__SYS_REGIST_TYPE(long double);
#endif	//	defined(_MSC_VER)


#else	//	defined(__cplusplus)
#define	LOLIX_DEF__SYS_REGIST_TYPE(type)
#endif	//	defined(__cplusplus)
#endif	//	!defined(__LOLIX__TOY__REBIND_TYPE__K_IN_G__)
